home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
pennmush.000
/
pennmush-1.50-p8-linux.tar
/
pennmush
/
mail.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-19
|
17KB
|
752 lines
/* mail.c -- linked list version by Amberyl */
#include <sys/time.h>
#include <string.h>
#include "config.h"
#include "db.h"
#include "interface.h"
#ifdef USE_MAILER
#define notify(p,m) notify_check(p,m,0)
extern char *tprintf();
extern char *strdup();
extern void do_log();
struct mail *maildb;
struct mail *tail_ptr;
#define HEAD maildb
#define TAIL tail_ptr
#define DASH_LINE \
"--------------------------------------------------------------------------"
int mdb_top = 0; /* total number of messages */
/*-------------------------------------------------------------------------*
* Basic mail functions
*-------------------------------------------------------------------------*/
struct mail *mail_fetch(player, num)
dbref player;
int num;
{
/* get an arbitrary mail message */
struct mail *mp;
int i = 0;
for (mp = HEAD; mp != NULL; mp = mp->next) {
if (mp->to == player)
i++;
if (i == num)
return mp;
}
return NULL;
}
static void count_mail(player, rcount, ucount)
dbref player;
int *rcount;
int *ucount;
{
/* returns count of read and unread messages as rcount and ucount */
struct mail *mp;
int rc, uc;
rc = uc = 0;
for (mp = HEAD; mp != NULL; mp = mp->next) {
if (mp->to == player) {
if (mp->read)
rc++;
else
uc++;
}
}
*rcount = rc;
*ucount = uc;
}
void check_mail(player, show)
dbref player;
int show;
{
/* list all mail messages.
* if !show, then just count the number of messages
*/
struct mail *mp;
int i = 0;
int rc; /* read messages */
int uc; /* unread messages */
if (show) {
/* show all messages */
notify(player,
"-------------------------------- MAIL --------------------------------");
for (mp = HEAD; mp != NULL; mp = mp->next) {
if (mp->to == player) {
i++;
notify(player, tprintf("[%c] %-3d From: %-*s Time: %s",
(mp->read) ? ' ' : '*',
i,
PLAYER_NAME_LIMIT + 1, Name(mp->from),
uncompress(mp->time)));
}
}
notify(player, DASH_LINE);
} else {
/* just count messages */
count_mail(player, &rc, &uc);
if (rc + uc > 0)
notify(player,
tprintf("\nMAIL: You have %d messages (%d unread).\n",
rc + uc, uc));
else
notify(player, tprintf("\nMAIL: You have no mail.\n"));
return;
}
}
void read_mail(player, num)
dbref player;
int num;
{
/* print a mail message */
struct mail *mp;
mp = mail_fetch(player, num);
if (mp != NULL) {
notify(player, DASH_LINE);
notify(player, tprintf("From: %-*s Time: %-25s Status: %s",
PLAYER_NAME_LIMIT + 1, Name(mp->from),
uncompress(mp->time),
(mp->read) ? "Read" : "Unread"));
notify(player, DASH_LINE);
notify(player, uncompress(mp->message));
notify(player, DASH_LINE);
mp->read = 1; /* mark message as read */
return;
}
/* ran off the end of the list without finding anything */
notify(player, "You don't have that many messages!");
return;
}
void send_mail(player, target, message)
dbref player;
dbref target;
const char *message;
{
/* send a mail message */
struct mail *newp;
time_t tt;
char tbuf1[30];
if (Typeof(target) != TYPE_PLAYER) {
notify(player, "You cannot send mail to non-existent people.");
return;
}
tt = time(NULL);
strcpy(tbuf1, ctime(&tt));
tbuf1[strlen(tbuf1) - 1] = '\0'; /* whack the newline */
/* initialize the appropriate fields */
newp = (struct mail *) malloc(sizeof(struct mail));
newp->to = target;
newp->from = player;
newp->message = (char *) strdup(compress(message));
newp->time = (char *) strdup(compress(tbuf1));
newp->read = 0;
newp->prev = TAIL;
newp->next = NULL;
/* if this is the first message, it is the head and the tail */
if (mdb_top == 0) {
HEAD = newp;
TAIL = newp;
} else
TAIL->next = newp;
/* the new message becomes the tail */
TAIL = newp;
mdb_top++;
/* notify people */
notify(player, tprintf("You sent your message to %s.", Name(target)));
notify(target, tprintf("MAIL: You have a new message from %s.",
Name(player)));
return;
}
void clear_mail(player, num)
dbref player;
int num;
{
/* if num is 0, clear all of the player's mail. Otherwise, clear one. */
struct mail *mp, *nextp;
if (!num) {
/* clear all */
for (mp = HEAD; mp != NULL; mp = nextp) {
if (mp->to == player) {
/* head and tail of the list are special */
if (mp == HEAD)
HEAD = mp->next;
else if (mp == TAIL)
TAIL = mp->prev;
/* relink the list */
if (mp->prev != NULL)
mp->prev->next = mp->next;
if (mp->next != NULL)
mp->next->prev = mp->prev;
/* save the pointer */
nextp = mp->next;
/* then wipe */
mdb_top--;
free(mp->message);
free(mp->time);
free(mp);
} else
nextp = mp->next;
}
notify(player, "Mailbox cleared.");
return;
} else {
/* find the message and clear just that one */
mp = mail_fetch(player, num);
if (mp != NULL) {
/* got it. delete. */
/* head and tail of the list are special */
if (mp == HEAD)
HEAD = mp->next;
else if (mp == TAIL)
TAIL = mp->prev;
/* relink the list */
if (mp->prev != NULL)
mp->prev->next = mp->next;
if (mp->next != NULL)
mp->next->prev = mp->prev;
/* then wipe */
mdb_top--;
free(mp->message);
free(mp->time);
free(mp);
notify(player, tprintf("Message #%d cleared.", num));
return;
}
/* didn't find anything */
notify(player, "You don't have that many messages!");
return;
}
}
void purge_mail(player)
dbref player;
{
/* wipes the entire maildb */
struct mail *mp, *nextp;
if (!Wizard(player)) {
notify(player, "The postal service issues a warrant for your arrest.");
return;
}
/* walk the list */
for (mp = HEAD; mp != NULL; mp = nextp) {
nextp = mp->next;
free(mp->message);
free(mp->time);
free(mp);
}
HEAD = TAIL = NULL;
mdb_top = 0;
do_log(LT_ERR, 0, 0, "** MAIL PURGE ** done by %s(#%d).",
Name(player), player);
notify(player, "You annihilate the post office. All messages cleared.");
}
void do_mail_debug(player, action, victim)
dbref player;
char *action;
char *victim;
{
/* how to fix mail with a sledgehammer */
dbref target;
struct mail *mp;
int i;
if (!Wizard(player)) {
notify(player, "Go get some bugspray.");
return;
}
if (string_prefix("clear", action)) {
target = lookup_player(victim);
if (target == NOTHING) {
init_match(player, victim, NOTYPE);
match_absolute();
target = match_result();
}
if (target == NOTHING) {
notify(player, tprintf("%s: no such player.", victim));
return;
}
clear_mail(target, 0);
notify(player, tprintf("Mail cleared for %s(#%d).", Name(target), target));
return;
} else if (string_prefix("sanity", action)) {
for (i = 0, mp = HEAD; mp != NULL; i++, mp = mp->next) {
if (!GoodObject(mp->to))
notify(player, tprintf("Bad object #%d has mail.", mp->to));
else if (Typeof(mp->to) != TYPE_PLAYER)
notify(player, tprintf("%s(#%d) has mail but is not a player.",
Name(mp->to), mp->to));
}
if (i != mdb_top) {
notify(player,
tprintf(
"Mail database top is %d, actual message count is %d. Fixing.",
mdb_top, i));
mdb_top = i;
}
notify(player, "Mail sanity check completed.");
} else {
notify(player, "That is not a debugging option.");
return;
}
}
void do_mail_stats(player, name, full)
dbref player;
char *name;
int full;
{
/* mail database statistics */
dbref target;
int fr, fu, tr, tu, fchars, tchars;
char last[50];
struct mail *mp;
fr = fu = tr = tu = fchars = tchars = 0;
/* find player */
if (*name == '\0') {
if Wizard(player)
target = AMBIGUOUS;
else
target = player;
} else if (*name == NUMBER_TOKEN) {
target = atoi(&name[1]);
if (!GoodObject(target) || (Typeof(target) != TYPE_PLAYER))
target = NOTHING;
} else if (!strcasecmp(name, "me")) {
target = player;
} else {
target = lookup_player(name);
}
if (target == NOTHING) {
init_match(player, name, NOTYPE);
match_absolute();
target = match_result();
}
if (target == NOTHING) {
notify(player, tprintf("%s: No such player.", name));
return;
}
if (!Wizard(player) && (target != player)) {
notify(player, "The post office protects privacy!");
return;
}
/* this comand is computationally expensive */
if (options.daytime) {
notify(player, "Sorry, that command has been temporarily disabled.");
return;
}
if (!payfor(player, FIND_COST)) {
notify(player, tprintf("Finding mail stats costs %d %s.", FIND_COST,
(FIND_COST == 1) ? MONEY: MONIES));
return;
}
if (target == AMBIGUOUS) { /* stats for all */
if (full == 0) {
notify(player,
tprintf("There are %d messages in the mail spool.", mdb_top));
return;
} else if (full == 1) {
for (mp = HEAD; mp != NULL; mp = mp->next) {
if (mp->read)
fr++;
else
fu++;
}
notify(player,
tprintf("There are %d messages in the mail spool, %d unread.",
fr + fu, fu));
return;
} else {
for (mp = HEAD; mp != NULL; mp = mp->next) {
if (mp->read) {
fr++;
fchars += strlen((char *) uncompress(mp->message));
} else {
fu++;
tchars += strlen((char *) uncompress(mp->message));
}
}
notify(player,
tprintf(
"There are %d old messages in the mail spool, totalling %d characters.",
fr, fchars));
notify(player,
tprintf(
"There are %d new messages in the mail spool, totalling %d characters.",
fu, tchars));
return;
}
}
/* individual stats */
if (full == 0) {
/* just count number of messages */
for (mp = HEAD; mp != NULL; mp = mp->next) {
if (mp->from == target)
fr++;
if (mp->to == target)
tr++;
}
notify(player, tprintf("%s sent %d messages.",
Name(target), fr));
notify(player, tprintf("%s has %d messages.", Name(target), tr));
return;
}
/* more detailed message count */
for (mp = HEAD; mp != NULL; mp = mp->next) {
if (mp->from == target) {
if (mp->read)
fr++;
else
fu++;
if (full == 2)
fchars += strlen((char *) uncompress(mp->message));
}
if (mp->to == target) {
if (!tr && !tu)
strcpy(last, (char *) uncompress(mp->time));
if (mp->read)
tr++;
else
tu++;
if (full == 2)
tchars += strlen((char *) uncompress(mp->message));
}
}
notify(player, tprintf("Mail statistics for %s:", Name(target)));
if (full == 1) {
notify(player, tprintf("%d messages sent, %d unread.", fr + fu, fu));
notify(player, tprintf("%d messages received, %d unread.", tr + tu, tu));
} else {
notify(player,
tprintf("%d messages sent, %d unread, totalling %d characters.",
fr + fu, fu, fchars));
notify(player,
tprintf("%d messages received, %d unread, totalling %d characters.",
tr + tu, tu, tchars));
}
if (tr + tu > 0)
notify(player, tprintf("Last is dated %s", last));
return;
}
/*-------------------------------------------------------------------------*
* Main mail routine
*-------------------------------------------------------------------------*/
void do_mail(player, arg1, arg2)
dbref player;
char *arg1;
char *arg2;
{
int num;
dbref target;
if (Typeof(player) != TYPE_PLAYER) {
notify(player, "Only players may send and receive mail.");
return;
}
if (!arg1 || !*arg1) {
if (arg2 && *arg2) {
notify(player, "Invalid mail command.");
return;
}
/* just the "@mail" command */
check_mail(player, 1);
return;
}
/* purge maildb */
if (!strcasecmp(arg1, "mdb-purge")) {
purge_mail(player);
return;
}
/* clear message */
if (!strcasecmp(arg1, "clear")) {
if (arg2 && *arg2) {
/* one message */
num = atoi(arg2);
if (!num) {
notify(player, "Invalid message number.");
return;
}
clear_mail(player, num);
return;
} else {
/* all messgaes */
clear_mail(player, 0);
return;
}
}
if (arg2 && *arg2) {
num = atoi(arg1);
if (num) {
/* reply to a mail message */
struct mail *temp;
temp = mail_fetch(player, num);
if (!temp) {
notify(player, "You can't reply to nonexistant mail.");
return;
}
send_mail(player, temp->from, arg2);
return;
} else {
/* send a new mail message */
if (!arg2 || !*arg2) {
notify(player, "You can't send blank messages.");
return;
}
target = lookup_player(arg1);
if ((target == NOTHING) || (Typeof(target) != TYPE_PLAYER)) {
notify(player, "No such player.");
return;
}
send_mail(player, target, arg2);
return;
}
} else {
/* attempt to read a mail message */
num = atoi(arg1);
if (!num) {
notify(player, "Invalid mail message.");
return;
}
read_mail(player, num);
return;
}
/* if we've hit this point, something is wrong */
do_log(LT_ERR, 0, 0,
"MAIL COMMAND PROBLEM: player = %d, arg1 = %s, arg2 = %s",
player, arg1, arg2);
return;
}
/*-------------------------------------------------------------------------*
* Auxiliary functions
*-------------------------------------------------------------------------*/
void fun_mail(buff, args, nargs, privs, dumm1)
char *buff;
char *args[10];
int nargs;
dbref privs;
dbref dumm1;
{
/* This function can take one of three formats:
* 1. mail(num) --> returns message <num> for privs.
* 2. mail(player) --> returns number of messages for <player>.
* 3. mail(player, num) --> returns message <num> for <player>.
*/
struct mail *mp;
dbref player;
int num, rc, uc;
/* make sure we have the right number of arguments */
if ((nargs != 1) && (nargs != 2)) {
strcpy(buff, "#-1 FUNCTION (MAIL) EXPECTS 1 OR 2 ARGUMENTS");
return;
}
if (nargs == 1) {
if (!is_number(args[0])) {
/* handle the case of wanting to count the number of messages */
if ((player = lookup_player(args[0])) == NOTHING) {
strcpy(buff, "#-1 NO SUCH PLAYER");
return;
} else if ((privs != player) && !Wizard(privs)) {
strcpy(buff, "#-1 PERMISSION DENIED");
return;
} else {
count_mail(player, &rc, &uc);
sprintf(buff, "%d %d", rc, uc);
return;
}
} else {
player = privs;
num = atoi(args[0]);
}
} else {
if ((player = lookup_player(args[0])) == NOTHING) {
strcpy(buff, "#-1 NO SUCH PLAYER");
return;
} else if ((privs != player) && !Wizard(privs)) {
strcpy(buff, "#-1 PERMISSION DENIED");
return;
}
num = atoi(args[1]);
}
if ((num < 1) || (num > mdb_top) || (Typeof(player) != TYPE_PLAYER)) {
strcpy(buff, "#-1 NO SUCH MESSAGE");
return;
}
mp = mail_fetch(player, num);
if (mp != NULL) {
strcpy(buff, (char *) uncompress(mp->message));
return;
}
/* ran off the end of the list without finding anything */
strcpy(buff, "#-1 NO SUCH MESSAGE");
}
int dump_mail(fp)
FILE *fp;
{
struct mail *mp;
int count = 0;
fprintf(fp, "%d\n", mdb_top);
for (mp = HEAD; mp != NULL; mp = mp->next) {
putref(fp, mp->to);
putref(fp, mp->from);
putstring(fp, uncompress(mp->time));
putstring(fp, uncompress(mp->message));
putref(fp, mp->read);
count++;
}
fprintf(fp, "*** END OF DUMP ***\n");
fflush(fp);
if (count != mdb_top) {
do_log(LT_ERR, 0, 0, "MAIL: Count of messages is %d, mdb_top is %d.",
count, mdb_top);
/* mdb_top = count; */
/* Removed since it won't make a difference unless the process isn't forked */
}
return (count);
}
void mail_init()
{
mdb_top = 0;
HEAD = NULL;
TAIL = NULL;
}
int load_mail(fp)
FILE *fp;
{
char nbuf1[8];
int mail_top = 0;
int i = 0;
struct mail *mp, *prevp;
mail_init();
/* find out how many messages we should be loading */
fgets(nbuf1, sizeof(nbuf1), fp);
mail_top = atoi(nbuf1);
/* first one is a special case */
mp = (struct mail *) malloc(sizeof(struct mail));
mp->to = getref(fp);
mp->from = getref(fp);
mp->time = (char *) strdup(compress(getstring_noalloc(fp)));
mp->message = (char *) strdup(compress(getstring_noalloc(fp)));
mp->read = getref(fp);
mp->next = NULL;
mp->prev = NULL;
HEAD = mp;
prevp = mp;
i++;
/* now loop through */
for ( ; i < mail_top; i++) {
mp = (struct mail *) malloc(sizeof(struct mail));
mp->to = getref(fp);
mp->from = getref(fp);
mp->time = (char *) strdup(compress(getstring_noalloc(fp)));
mp->message = (char *) strdup(compress(getstring_noalloc(fp)));
mp->read = getref(fp);
mp->next = NULL;
mp->prev = prevp;
prevp->next = mp;
prevp = mp;
}
TAIL = mp;
mdb_top = i;
if (i != mail_top) {
fprintf(stderr, "MAIL: mail_top is %d, only read in %d messages.\n",
mail_top, i);
}
return (mdb_top);
}
#endif /* USE_MAILER */